package com.epoint.juc.future;

import java.util.*;
import java.util.concurrent.*;

public class CompleFutureDemo {

    public static void main(String[] args) throws ExecutionException, InterruptedException {
//        int corePoolSize,
//        int maximumPoolSize,
//        long keepAliveTime,
//        TimeUnit unit,
//        BlockingQueue<Runnable> workQueue,
//        ThreadFactory threadFactory,
//        RejectedExecutionHandler handler
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(5, 10, 5,
                TimeUnit.SECONDS, new LinkedBlockingQueue<>(10),
                Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy());

        Map<String, Integer> map = new HashMap<>();

        CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(() -> {
            System.out.println(getThreadName() + "任务1：执行~");
            int i = 10/0;
            return 100;
        }, threadPoolExecutor).whenCompleteAsync((u, t)->{ // 虽然能感知到异常，但是不能进行try处理
            System.out.println(getThreadName() + "任务1：whenCompleteAsync：返回值：" + u);
            System.out.println(getThreadName() + "任务1：whenCompleteAsync：异常捕捉：" + t);
        }, threadPoolExecutor).exceptionally((e)->{ // 能够捕捉到异常而不是直接再系统中报错
            System.out.println(getThreadName() + "任务1：exceptionally：返回值：" + e);
            return 200;
        }).handleAsync((u, t)->{ // 相当于 whenCompleteAsync  +  exceptionally 的活都给handle做了，推荐使用，而且还能修改返回值
            System.out.println(getThreadName() + "任务1：handleAsync：返回值：" + u);
            System.out.println(getThreadName() + "任务1：handleAsync：异常捕捉：" + t);

            map.put("1", 300);
            return 300;
        }, threadPoolExecutor);

        // 任务2 基于任务1的返回值
        CompletableFuture<Integer> future2 = future1.thenApplyAsync((e) -> {
            System.out.println(getThreadName() + "任务2：thenApplyAsync：返回值：" + e);
            map.put("2", 400);
            return 400;
        }, threadPoolExecutor);

        // 任务3 基于任务1的返回值
        CompletableFuture<Integer> future3 = future1.thenApplyAsync((e) -> {
            System.out.println(getThreadName() + "任务3：thenApplyAsync：返回值：" + e);

            map.put("3", 500);
            return 500;
        }, threadPoolExecutor);

        CompletableFuture<Void> voidCompletableFuture = CompletableFuture.allOf(future1, future2, future3);
        voidCompletableFuture.get();

        // 所有的数据都封装到这个map里了
        System.out.println(map);

        threadPoolExecutor.shutdown();
    }

    public static String getThreadName(){
        return Thread.currentThread().getName();
    }
}
